#!/usr/bin/env python
# coding: utf-8
#from typing import Dict, Union
from datetime import datetime, timedelta
import freeswitch
from rediscluster import client
import time
import random
import demjson
import json


# 此运行在python2 上面，编码方面不太一样
# new: 加入LastCallInfo支持呼入
#此版本已OK，下一版：LastCallInfo存入redis的格式改成智能外呼呼入时需要的格式
###
# rdc.get_state()
# rdc.get_cop_num('20358')
# rdc.get_last_call_info('LastCallInfo:02023398853:13724059427')

class RedisClusterClient(object):
    instance = None
    city_show_num_pool_index_prix = "copShowNumIndex:"
    city_show_num_pool_list_prix = "copShowNumList:"
    last_call_info_prix = "LastCallInfo:"

    def __init__(self, conn_list):
        self.conn_list = conn_list
        RedisClusterClient.instance = self.connect()

    def connect(self):
        """
        init connection
        :return: object
        """
        try:
            # 非密码连接redis集群
            # redisconn = StrictRedisCluster(startup_nodes=self.conn_list)
            # 使用密码连接redis集群
            redisconn = client.RedisCluster(startup_nodes=self.conn_list)
            return redisconn
        except Exception as e:
            print(e)
            return False

    def get_state(self):
        """
        :return:
        """
        res = RedisClusterClient(self.conn_list).connect()
        if not res:
            return False

        dic = res.cluster_info()

        for i in dic:
            ip = i.split(":")[0]
            if dic[i].get('cluster_state'):
                print("status, ip: ", ip, "value: ", dic[i].get('cluster_state'))

    def get_cop_show_num_dict(self, user_id):
        if user_id is None:
            return None
        key = "copShowNumMap:%s" % user_id
        return RedisClusterClient.instance.hgetall(name=key)

    def get_cop_num(self, user_id, city=None):

        b_show_num_dict = self.get_cop_show_num_dict(user_id)
        if b_show_num_dict is None:
            return None
        if city is None:
            """
            direct random one from own show number,if without city param
            """
            if len(b_show_num_dict) > 0:
                rl = list(b_show_num_dict.keys())
                return random.choice(rl)
        else:
            """
            random one from own show number,in a city showNum list
            """
            show_num_list = [x for x, y in b_show_num_dict.items() if y is city]
            if len(show_num_list) > 0:
                return random.choice(show_num_list)

        return None

    def get_cop_num_in_pool(self, city):
        """Take turns getting a display number in a city's number pool"""
        index_key = RedisClusterClient.city_show_num_pool_index_prix + city
        list_key = RedisClusterClient.city_show_num_pool_list_prix + city
        pool_size = RedisClusterClient.instance.llen(list_key)
        if pool_size is None or pool_size == 0:
            return None

        current_index = RedisClusterClient.instance.incr(index_key)

        if current_index >= pool_size:
            RedisClusterClient.instance.delete(index_key)

        show_num = RedisClusterClient.instance.lindex(list_key, current_index)
        if show_num is not None:
            return show_num

        return None

    def add_last_call_info(self, show_num, target_call_phone, call_info_dict):
        key = RedisClusterClient.last_call_info_prix + show_num + ":" + target_call_phone
        freeswitch.consoleLog("info", key +" \n")
        RedisClusterClient.instance.hmset(key, call_info_dict)
        RedisClusterClient.instance.expire(key, timedelta(days=30))
        #pipe = RedisClusterClient.instance.pipeline()
        #pipe.hmset(key, call_info_dict)
        #pipe.expire(key, timedelta(days=30).total_seconds())
        #pipe.execute()

    def get_last_call_info(self, key):
        b_last_call_info_dict = RedisClusterClient.instance.hgetall(key)
        return b_last_call_info_dict


call_prix_dict = {
    '1': '98',
    '2': '97',
    '3': '96'
}
nodes = [
    {'host': '172.16.200.35', 'port': 6379},
    {'host': '172.16.200.36', 'port': 6379},
    {'host': '172.16.200.37', 'port': 6379},
    {'host': '172.16.200.38', 'port': 6379},
    {'host': '172.16.200.39', 'port': 6379},
    {'host': '172.16.200.40', 'port': 6379}
]

# init
rdc = RedisClusterClient(nodes)


def handler(session, args):  # args is string
    session.setAutoHangup(False)
    uuid = session.getVariable("uuid")

    if args is None:
        freeswitch.console_log("info", "call %s has no target call number in args param\n" % uuid)
        session.hangup("UNALLOCATED_NUMBER")
        return

    freeswitch.console_log("info", "call %s args string is: %s \n" % (uuid, args))

    X_uuid = session.getVariable("sip_h_X-uuid")
    X_create_user_id = session.getVariable("sip_h_X-create_user_id")
    X_city = session.getVariable("sip_h_X-city")

    if X_create_user_id is None or X_city is None or X_uuid is None:
        freeswitch.console_log("info", "X_uuid and X_create_user_id and X_uuid is required !")
        session.hangup("UNALLOCATED_NUMBER")
        return

    freeswitch.console_log("info", "city type str: %s \n" % isinstance(X_city, str))
    freeswitch.console_log("info", "X_create_user_id type str: %s \n" % isinstance(X_create_user_id, str))

    X_uuid = X_uuid.strip()
    X_create_user_id = X_create_user_id.strip()
    X_city = X_city.strip()

    freeswitch.consoleLog("info", "call %s extend params: X_uuid: %s, X_create_user_id: %s, X_city: %s \n" %
                          (uuid, X_uuid, X_create_user_id, X_city))
    # X_main_call_phone: 13724059427',
    # X_target_call_phone: 13523236314',
    # X_show_num: 18600000000',

    X_where_from = session.getVariable("sip_h_X-where_from")
    X_page_from = session.getVariable("sip_h_X-page_from")
    X_enroll_num = session.getVariable("sip_h_X-enroll_num")
    # X_reg_psw = session.getVariable("sip_h_X-reg_psw")
    X_data_id = session.getVariable("sip_h_X-data_id")
    X_customer_name = session.getVariable("sip_h_X-customer_name")
    X_customer_no = session.getVariable("sip_h_X-customer_no")
    X_project_name = session.getVariable("sip_h_X-project_name")
    # X_token = session.getVariable("sip_h_X-token")
    X_package_id = session.getVariable("sip_h_X-package_id")
    X_call_task_id = session.getVariable("sip_h_X-call_task_id")
    freeswitch.consoleLog("info", "call %s extend params:X_where_from: %s,X_page_from: %s,X_enroll_num: %s,X_data_id: "
                                  "%s,X_customer_name: %s,X_customer_no: %s,X_project_name: %s,X_package_id: %s,"
                                  "X_call_task_id: %s \n" %
                          (uuid, X_where_from, X_page_from, X_enroll_num, X_data_id, X_customer_name, X_customer_no,
                           X_project_name, X_package_id, X_call_task_id))
    try:
        # unicode
        # show_num = rdc.get_cop_num(X_create_user_id, X_city)

        # in city show_num pool mode
        show_num = rdc.get_cop_num_in_pool(X_city)

        # show_num_dict = rdc.get_cop_show_num_dict(X_create_user_id)
        # freeswitch.console_log("info", demjson.encode(show_num_dict, 'utf-8'))
        # show_num = "1002"
        if show_num is None:
            freeswitch.console_log("info", "get show_num from redis cluster is None,"
                                           "with user_id: %,city: % \n" % (X_create_user_id, X_city))
            session.hangup("UNALLOCATED_NUMBER")
            return

        show_num = show_num.strip('\"')
        #show_num = show_num.encode('utf-8')
        freeswitch.console_log("err", "show_num: %s, type: %s \n" % (show_num, type(show_num)))

        call_info_dict = {
            'cityId': X_city,
            'dataId': X_data_id if X_data_id is not None else "-1",
            'enrollNum': X_enroll_num if X_enroll_num is not None else "-1",
            'userId': X_create_user_id,
            'direct_call': 'true'
        }
        p_dict = {
            'mainCallPhone': session.getVariable("sip_from_user"),
            'targetCallPhone': args,
            'commitTime': time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
            'callTaskId': X_call_task_id if X_call_task_id is not None else "-1",
            'packageId': X_package_id if X_package_id is not None else "-1",
            'whereFrom': X_where_from if X_where_from is not None else "-1",
            'pageFrom': X_page_from if X_page_from is not None else "-1",
            'projectName': X_project_name if X_project_name is not None else "-1",
            'customerName': X_customer_name if X_customer_name is not None else "-1",
            'customerNo': X_customer_no if X_customer_no is not None else "-1"
        }
        call_info_dict['popupWindowId'] = json.dumps(p_dict)
        rdc.add_last_call_info(show_num, args, call_info_dict)

        session.setVariable("continue_on_fail", "false")
        session.setVariable("hangup_after_bridge", "true")
        session.setVariable("jitterbuffer_msec", "260:400:20")
        session.execute("export", "session_id=${uuid}")
        session.execute("export", "call_timeout=60")
        # TODO ????
        session.setHangupHook("hangup_hook")
        # save record file
        today = time.strftime("%Y%m%d", time.localtime())

        record_save_base_paths = ["/cloudcall_file/rec_20050/freeswitchRecordFile/",
                                  "/cloudcall_file/rec_20051/freeswitchRecordFile/"]
        path = random.choice(record_save_base_paths) + today + "/" + uuid + ".wav"
        freeswitch.console_log("info", "choice path: %s" % path)
        session.execute("export", "nolocal:execute_on_answer=record_session " + path)

        call_prix = call_prix_dict[X_city]
        call_str = "{origination_caller_id_number=%s,origination_caller_id_name=%s}" \
                   "sofia/external/%s%s@10.41.46.57:5060" % (show_num, show_num, call_prix, args)
        freeswitch.console_log("info", "bridge string is: %s \n" % call_str)
        # session.execute("bridge", "user/%s" % args)
        session.execute("bridge", call_str)
        session.hangup()
    except Exception as err:
        freeswitch.console_log("err", "call %s exception,msg: %s \n" % (uuid, err))
        session.hangup("ORIGINATOR_CANCEL")


def hangup_hook(uuid):
    freeswitch.console_log("info", "myHangupHook, uuid: %s!!\n" % uuid)
    return "Result"